#include <iostream>
#include <fstream>
#include <cstring>

using std::ifstream;
using std::string;

struct Task
{
    string filename;
    int mapId;
    int reduceId;
    Task(string file, int id): filename(file), mapId(id){};
    Task(int id): reduceId(id){};
};

struct TaskResponse
{
    int state;          //当前状态
    Task curTask;       //当前任务
    int mapTask;        // 待分配的map任务数目
    int reduceTask;     // 待分配的reduce任务数目
    int mapTaskTotal;   // 总map任务数量
    int reduceTaskTotal;// 总reduce任务数量
};

struct KeyValue
{
    string key;
    string value;
};

// 将原始文件转为 文件名->文件内容 的kv
KeyValue getContent(const string &file)
{
    std::ifstream inputFile(file);
    if (!inputFile.is_open())
    {
        std::cerr << "Failed to open file : " << file << std::endl;
        exit(-1);
    }

    std::stringstream buffer;
    buffer << inputFile.rdbuf();
    string fileContent = buffer.str();

    KeyValue kv;
    kv.key = file;
    kv.value = fileContent;

    inputFile.close();
    return kv;
}

// 分割字符串到vector中
vector<string> split(char *content, int len)
{
    vector<string> str;
    string tmp = "";
    while (len--)
    {
        if (isalpha(*content))
        {
            tmp += *content;
        }
        else
        {
            if (tmp.size())
                str.emplace_back(tmp);
            tmp = "";
        }
        ++content;
    }
    return str;
}

// 将文件内容转为{word,1}的KeyValue，me and you --> {{me,1},{and,1},{you,1}}
vector<KeyValue> mapF(KeyValue &kv)
{
    vector<KeyValue> kvs;
    int len = kv.value.size();
    char content[len + 1];
    strcpy(content, kv.value.c_str());
    vector<string> str = split(content, len);
    for (auto &s : str)
    {
        KeyValue tmp = {s, "1"};
        kvs.emplace_back(tmp);
    }
    return kvs;
}

// 对每个word求hash值映射到对应的reduce线程
int hashFunc(string &s)
{
    int hash = 0;
    for (auto &c : s)
        hash = hash * c + 7;
    return hash;
}

// 将kvs(map结果)输出到中间文件,
void writeOutMap(vector<KeyValue> &kvs, int mapId, int reduceTaskNum)
{
    for (auto &kv : kvs)
    {
        int reduce_idx = hashFunc(kv.key) % reduceTaskNum;
        string path = "mr-" + std::to_string(mapId) + "-" + to_string(reduce_idx);

        std::ofstream outfile(path, std::ios::out | std::ios::app);
        if (!outfile.is_open())
        {
            std::cerr << "Failed to open file: " << path << std::endl;
            exit(-1);
        }
        else
        {
            std::string tmp = kv.key + ",1 ";
            outfile << tmp;
        }
        outfile.close();
    }
}